#include "GameLoop.h"
#include "DataBase.h"
#include "LogController.h"
#include <iostream>

std::vector<std::string> &split(const std::string &s, char delim, std::vector<std::string> &elems)
{
    std::stringstream ss(s);
    std::string item;
    while(std::getline(ss, item, delim)) {
        elems.push_back(item);
    }
    return elems;
}

std::vector<std::string> splitStr(const std::string &s, char delim = '#')
{
    std::vector<std::string> elems;
    return split(s, delim, elems);
}

GameLoop::GameLoop(void) : m_fps(2), m_window(sf::VideoMode(512, 512), "")
{
}

GameLoop::~GameLoop(void)
{
	this->m_timer.stop();
}

void	GameLoop::Run()
{
	int i = 1;
	this->m_timer.start();

	double nextTick = this->m_timer.getElapsedTimeInMilliSec() + (1000 / m_fps);

	while (this->m_timer.getElapsedTimeInMilliSec() > 0)
	{
		if (this->m_timer.getElapsedTimeInMilliSec() > nextTick)
		{
			nextTick = this->m_timer.getElapsedTimeInMilliSec() + (1000 / m_fps);
			if (i < m_fps)
			{
				if (!DataBase::getInstance()->m_alive)
					break;
				this->Update(this->m_timer.getElapsedTimeInMilliSec());
				this->Draw(this->m_timer.getElapsedTimeInMilliSec());
				i++;
			}
			else
			{
				i = 1;
			}
		}
	}
	this->m_timer.stop();
}

void	GameLoop::Initialize()
{
	LogController::getInstance()->AddToLog(LogController::L_NOTICE, "Initialize gameloop");

	m_window.setTitle("The Hunter server - Map viewer");

	LogController::getInstance()->AddToLog(LogController::L_NOTICE, "Start gameloop");
	this->Run();
}

void	GameLoop::Update(double time)
{
	sf::Event	event;
	void*		buffer;

	while (m_window.pollEvent(event))
	{
		if (event.type == sf::Event::Closed)
			m_window.close();
	}

	for (int it=0; it < DataBase::getInstance()->getSizeStackRecv(); it++)
	{
		SPacket *p = DataBase::getInstance()->popStackRecv();
		if (p == NULL)
			break;

		std::string t = p->hp.m_infos_cmd.toAnsiString();
		std::string temp = t.c_str();
	
	//	std::cout << "RAW BUFFER '" << temp << "'" << std::endl;
		std::vector<std::string> tempo = splitStr(temp.c_str());

		if(tempo.size() < 3)
			break;

		int x = (atoi(tempo[0].c_str()));
		int y = (atoi(tempo[1].c_str()));
		int nb = atoi(tempo[2].c_str());

		for (int it=0; it < DataBase::getInstance()->getSizeClients(); it++)
		{
			Client *c = DataBase::getInstance()->getElementAt(it);
			if (nb == c->m_number)
			{
				//std::cout << "NEW POSITION FOR PLAYER " << c->m_number << " X " << x << " Y " << y << std::endl;
				c->m_posX = x;
				c->m_posY = y;
				break;
			}
		}
		delete p;
	}

	SendAllPosition();

	//LogController::getInstance()->AddToLog(LogController::L_NOTICE, "Update gameloop");
}

void	GameLoop::Draw(double time)
{
	/*for (int it = 0; it < DataBase::getInstance()->getSizeClients(); it++)
	{
		Client *c = DataBase::getInstance()->getElementAt(it);
		std::cout << "NB CLIENT : " << c->m_number << std::endl;
	}*/
	m_window.clear();

	sf::CircleShape circle;

	circle.setRadius(2);
	for(int it=0; it < DataBase::getInstance()->getSizeClients(); it++)
	{
		Client *c = DataBase::getInstance()->getElementAt(it);

		if (c->m_type == TypePlayer::MAN)	 
			circle.setOutlineColor(sf::Color::Red);
		else
			circle.setOutlineColor(sf::Color::Blue);

		circle.setOutlineThickness(5);
		circle.setPosition((c->m_posX  + 512) / 2, (c->m_posY + 512) / 2);

		m_window.draw(circle);
	}
	m_window.display();

	//LogController::getInstance()->AddToLog(LogController::L_NOTICE, "Draw gameloop");
}

void	GameLoop::SetFps(int fps)
{
	this->m_fps = fps;
}


void GameLoop::SendAllPosition()
{
	std::string format;

	format = "";
	std::ostringstream out1, out2, out3;
	for (int it = 0; it < DataBase::getInstance()->getSizeClients(); it++)
	{
		Client *c = DataBase::getInstance()->getElementAt(it);
	
		out1.str("");
		out2.str("");
		out3.str("");

		out1 << c->m_posX;
		out2 << c->m_posY;
		out3 << c->m_number;

		if (format != "")
			format += "/";
		format += out1.str() + "#" + out2.str() + "#" + out3.str();
	}

	//std::cout << "FORMAT : " << format << std::endl;
	for (int it = 0; it < DataBase::getInstance()->getSizeClients(); it++)
	{
		Client *c = DataBase::getInstance()->getElementAt(it);
		SPacket *sp = new SPacket;

		sp->s = c->m_socket;
		sp->hp.m_cmd_number = 4;
		sp->hp.m_infos_cmd = sf::String(format);
		sp->hp.m_time = sf::String("34567");
		DataBase::getInstance()->pushStackSend(sp);
	}

}